from flask import abort
from flask import current_app
from flask import g, jsonify
from flask import render_template
from flask import request
from flask import session

from info import constants
from info import db
from info.models import Category, News, User
from info.modules.profile import profile_blu

from info.utils.commons import login_required
from info.utils.image_storage import storage
from info.utils.response_code import RET


# /user/<int:user_id>/news?p=page
@profile_blu.route('/<int:user_id>/news')
@login_required
def user_others_news(user_id):
    """
    查看其他用户发布的新闻列表
    """
    # 获取page
    try:
        page = request.args.get('p', 1)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 根据user_id获取作者的信息
    try:
        auther = User.query.get(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询用户失败')
    if not auther:
        return jsonify(errno=RET.NODATA, errmsg='用户不存在')
    # 根据auther查询发布所有的新闻信息并分页
    try:
        pagination = auther.news_list.paginate(page, constants.OTHER_NEWS_PAGE_MAX_COUNT, False)
        news_li = pagination.items
        total_pages = pagination.pages
        current_page = pagination.page
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取用户发布的新闻信息失败')
    news_li_dict = []
    for news in news_li:
        news_li_dict.append(news.to_basic_dict())
    # 返回应答 查询用户发布的新闻成功
    return jsonify(errno=RET.OK, errmsg='获取用户发布的新闻信息成功',
                   news_li=news_li_dict,
                   total_pages=total_pages,
                   current_page=current_page)


# /user/<int:user_id>
@profile_blu.route('/<int:user_id>')
@login_required
def user_others(user_id):
    """
    查看其他用户的页面
    """
    # 获取登陆的用户
    user = g.user
    # 根据user_id获取作者的信息

    try:
        author = User.query.get(user_id)
    except Exception as e:
        current_app.logger.error(e)
        abort(500)
    if not author:
        abort(404)

    return render_template('news/other.html',
                           user=user,
                           author=author,
                           qiniu_demo=constants.QINIU_DOMIN_PREFIX)


# /user/follows
@profile_blu.route('/follows')
@login_required
def user_follows():
    """
    我的关注列表
    """
    # 1.获取页码
    page = request.args.get('p', 1)
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 2.获取关注的用户的信息并分页处理
    user = g.user
    try:
        pagination = user.followed.paginate(page, constants.USER_FOLLOWED_MAX_COUNT, False)
        follows = pagination.items
        total_pages = pagination.pages
        current_page = pagination.page
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询关注的用户信息失败')
    return render_template('news/user_follow.html',
                           follows=follows,
                           total_pages=total_pages,
                           current_page=current_page,
                           qiniu_demo=constants.QINIU_DOMIN_PREFIX)


# /user/follow
@profile_blu.route('/follow', methods=['POST'])
@login_required
def user_follow():
    """
    关注,取消关注
    :return:
    """
    # 1.接收参数(user_id,action)并校验参数
    req_dict = request.json
    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    user_id = req_dict.get('user_id')
    action = req_dict.get('action')
    if not all([user_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
    try:
        user_id = int(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    if action not in ('do', 'undo'):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 2.根据user_id 查询被关注的用户信息
    try:
        followde_user = User.query.get(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.NODATA, errmsg='用户不存在')
    # 3.根据action执行关注或者取消关注
    user = g.user
    if action == 'do':
        if user not in followde_user.followers:
            followde_user.followers.append(user)
    else:
        if user in followde_user.followers:
            followde_user.followers.remove(user)
    # 4.提交到数据库
    try:
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='操作失败')
    # 5.返回应答,关注或者取消关注成功
    return jsonify(errno=RET.OK, errmsg='操作成功')


# /user/news
@profile_blu.route('/news')
@login_required
def user_news_list():
    """
    用户发表新闻列表页面
    :return:
    """
    # 1.获取页码
    page = request.args.get('p', 1)
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 2.获取用户发布的新闻信息并进行分页处理
    user = g.user
    try:
        pagination = user.news_list.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        news_li = pagination.items
        total_pages = pagination.pages
        current_page = pagination.page
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询发布的新闻失败')
    return render_template('news/user_news_list.html',
                           news_li=news_li,
                           total_pages=total_pages,
                           current_page=current_page)


# /user/release
@profile_blu.route('/release', methods=['GET', 'POST'])
@login_required
def user_news_release():
    """
    新闻发布:
    :return:
    """
    if request.method == 'GET':
        # 获取所有新闻分类的信息
        try:
            categories = Category().query.all()
        except Exception as e:
            current_app.logger.error(e)
            abort(500)  # 报服务器出错 不让视图继续执行
        # 最新分类不需要展示 需要去掉
        categories.pop(0)
        return render_template('news/user_news_release.html',
                               categories=categories)
    else:
        """新闻发布"""
        user = g.user
        # 1.接收参数并进行校验
        title = request.form.get('title')
        category_id = request.form.get('category_id')
        digest = request.form.get('digest')
        content = request.form.get('content')
        file = request.files.get('index_image')
        if not all([title, category_id, digest, content, file]):
            return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
        try:
            category_id = int(category_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
        # 2. 根据category_id 查询分类信息
        try:
            category = Category.query.get(category_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.NODATA, errmsg='分类不存在')
        # 3.将新闻索引图片上传到qiniuyun
        try:
            key = storage(file.read())
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='上传失败')
        # 4.保存在数据库中
        news = News()
        news.title = title
        news.digest = digest
        news.source = '个人发布'
        news.content = content
        news.index_image_url = constants.QINIU_DOMIN_PREFIX + key
        news.category_id = category_id
        news.user_id = user.id
        news.status = 1  # 审核中
        try:
            db.session.add(news)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='保存新闻失败')
        # 5.返回应答,新闻发布成功
        return jsonify(errno=RET.OK, errmsg='新闻发布成功')


# /user/collection?p=page
@profile_blu.route('/collection')
@login_required
def user_collect():
    """
    用户收藏页面
    """
    # 1.获取页码
    page = request.args.get('p', 1)
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 2.获取用户收藏的新闻信息并进行分页处理
    user = g.user
    try:
        pagination = user.collection_news.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        news_li = pagination.items
        total_pages = pagination.pages
        current_page = pagination.page
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询收藏新闻失败')
    return render_template('news/user_collection.html',
                           news_li=news_li,
                           total_pages=total_pages,
                           current_page=current_page)


# user/password
@profile_blu.route('/password', methods=['GET', 'POST'])
@login_required
def user_password():
    """
    修改密码
    """
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')
    else:
        # 1.接收参数(old_password,new_password)并进行参数校验
        req_dict = request.json
        if not req_dict:
            return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
        old_password = req_dict.get('old_password')
        new_password = req_dict.get('new_password')
        if not all([old_password, new_password]):
            return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
        # 2.判断old_password是否正确
        user = g.user
        if not user.check_passowrd(old_password):
            return jsonify(errno=RET.DATAERR, errmsg='旧密码错误')
        # 3.设置新密码
        user.password = new_password
        # 4.保存到数据库中
        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='修改密码失败')
        # 5.返回应答,修改成功
        return jsonify(errno=RET.OK, errmsg='修改成功')


# user/avatar
@profile_blu.route('/avatar', methods=['GET', 'POST'])
@login_required
def user_avatar():
    """
    用户中心-头像设置
    """
    user = g.user
    if request.method == 'GET':
        return render_template('news/user_pic_info.html',
                               user=user)
    else:
        # 保存头像设置
        # 1.获取浏览器上传的头像文件
        file = request.files.get('avatar')
        if not file:
            return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
        # 2.上传头像文件到七牛云
        try:
            key = storage(file.read())
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.THIRDERR, errmsg='上传用户头像失败')
        # 3.设置数据表中用户的头像地址
        user.avatar_url = key
        # 4.上传到数据库中
        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='上传失败')
        # 5.返回应答,上传头像成功
        avatar_url = constants.QINIU_DOMIN_PREFIX + key
        return jsonify(errno=RET.OK, errmsg='上传成功',
                       avatar_url=avatar_url)


@profile_blu.route('/basic', methods=['GET', 'POST'])
@login_required
def user_basic():
    """
    用户中心-基本信息展示
    """
    user = g.user
    if request.method == 'GET':
        return render_template('news/user_base_info.html',
                               user=user)
    else:
        # 保存修改用户的信息
        # 1.接收参数(signature,nick_name,gender)并进行参数校验
        req_dict = request.json
        if not req_dict:
            return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
        signature = req_dict.get('signature')
        nick_name = req_dict.get('nick_name')
        gender = req_dict.get('gender')
        if not all([signature, nick_name, gender]):
            return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
        if gender not in ('WOMAN', 'MAN'):
            return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
        # 2.设置用户的个人信息
        user.signature = signature
        user.nick_name = nick_name
        user.gender = gender
        # 3.保存到数据库中
        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='保存失败')
        # 设置session中的nick_name
        session['nick_name'] = nick_name
        # 4.返回应答,保存信息成功
        return jsonify(errno=RET.OK, errmsg='操作成功')


@profile_blu.route('')
@login_required
def get_user_profile():
    """
    获取用户信息
    :return:
    """
    user = g.user
    return render_template('news/user.html',
                           user=user)
